﻿using System;
using System.Collections.Generic;
using System.Linq;
using Consul;
using IdentityServer4.AccessTokenValidation;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Ocelot.DependencyInjection;
using Ocelot.Middleware;

namespace OcelotService
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            List<AgentService> agentId4Services = new List<AgentService>();

            using (var consulClient = new ConsulClient(x =>
            {
                x.Address = new Uri("http://127.0.0.1:8500");
            }))
            {
                var consulServices = consulClient.Agent.Services().Result.Response;

                agentId4Services = consulServices.Values.Where(x =>
                x.Service.Equals("IdentityServer4V2Service", StringComparison.OrdinalIgnoreCase)).ToList();
            }


            var randomId4ServiceIndex = DateTime.Now.Second % agentId4Services.Count();
            var randomId4Service = agentId4Services.ElementAt(randomId4ServiceIndex);


            //指定Identity Server的信息
            Action<IdentityServerAuthenticationOptions> isaOptMsg = o =>
            {
                //o.Authority = "http://127.0.0.1:10101";
                o.Authority = $"http://{randomId4Service.Address}:{randomId4Service.Port}";
                o.ApiName = "MsgAPI";//要连接的应用的名字
                o.RequireHttpsMetadata = false;
                o.SupportedTokens = SupportedTokens.Both;
                o.ApiSecret = "HYD-PC-101:123654";//秘钥
            };

            Action<IdentityServerAuthenticationOptions> isaOptProduct1 = o =>
            {
                //o.Authority = "http://127.0.0.1:10101";
                o.Authority = $"http://{randomId4Service.Address}:{randomId4Service.Port}";
                o.ApiName = "ProductAPI";//要连接的应用的名字
                o.RequireHttpsMetadata = false;
                o.SupportedTokens = SupportedTokens.Both;
                o.ApiSecret = "HYD-PC-101:123654";//秘钥
            };

            Action<IdentityServerAuthenticationOptions> isaOptProduct2 = o =>
            {
                o.Authority = "http://127.0.0.1:10102";
                o.ApiName = "ProductAPI";//要连接的应用的名字
                o.RequireHttpsMetadata = false;
                o.SupportedTokens = SupportedTokens.Both;
                o.ApiSecret = "HYD-PC-101:123654";//秘钥
            };

            services.AddAuthentication()

            //对配置文件中使用 ChatKey 配置了 AuthenticationProviderKey=MsgKey 的路由规则使用如下的验证方式
            .AddIdentityServerAuthentication("MsgKey", isaOptMsg)
            .AddIdentityServerAuthentication("ProductKey", isaOptProduct1);
            //.AddIdentityServerAuthentication("ProductKey", isaOptProduct2);

            services.AddOcelot();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime applicationLifetime)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseMvc();

            var ip = Configuration["ip"];
            var port = Configuration["port"];
            var serviceName = "OcelotService";
            var serviceId = $"{serviceName }:{Guid.NewGuid()}";
            using (var consulClient = new ConsulClient(ConsulConfig))
            {
                AgentServiceRegistration service = new AgentServiceRegistration()
                {
                    ID = serviceId,
                    Name = serviceName,
                    Address = ip,
                    Port = Convert.ToInt32(port),
                    Check = new AgentServiceCheck()
                    {
                        HTTP = $"http://{ip}:{port}/api/health",
                        Interval = TimeSpan.FromSeconds(10),
                        Timeout = TimeSpan.FromSeconds(5),
                        DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5)
                    }
                };

                consulClient.Agent.ServiceRegister(service).Wait();
            }

            applicationLifetime.ApplicationStopped.Register(() =>
            {
                using (var consulClient = new ConsulClient(ConsulConfig))
                {
                    Console.WriteLine("应用推送，开始从Consul注销");
                    consulClient.Agent.ServiceDeregister(serviceId).Wait();
                }
            });

            app.UseOcelot().Wait();
        }

        private void ConsulConfig(ConsulClientConfiguration consulClientConfiguration)
        {
            consulClientConfiguration.Address = new Uri("http://127.0.0.1:8500");
            consulClientConfiguration.Datacenter = "dc1";
        }
    }
}
